package com.jdz.noise.tools;


import com.jdz.noise.dao.NoiseDao;
import com.jdz.noise.entities.*;
import net.sf.json.JSONArray;
import org.apache.ibatis.jdbc.Null;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class ControlUtil {
    //存储噪声文件数据
    public static final ArrayList<String> fileNames_noise = new ArrayList<String>();
    public static final ArrayList<NoiseRow> list_noise = new ArrayList<NoiseRow>();
    //存储飞行文件数据
    public static final ArrayList<String> fileNames_fly = new ArrayList<String>();
    public static final ArrayList<FlyRow> list_fly = new ArrayList<FlyRow>();
    //上传文件夹路径
    public static final String uploadPath = "E:/upload/";
    //标记飞行数据，还是噪声数据
    public static final int NOISE_TYPE = 1;
    public static final int FLY_TYPE = 2;
    //时间同步参数
    public static double[] gps_ground;
    public static double ori;
    public static double freq;
    //时间同步后的值后的Map
    public static Map<NoiseRow, FlyRow> noise_fly = new HashMap<NoiseRow, FlyRow>();
    //声道数
    public static int trackNum=0;
    //通过克里金插值算法形成的模型
    public static LinkedHashMap Map_3D_Noise=null;

    //存到文件夹里,返回文件路径
    public static String uploadFile(MultipartFile file, int fileType) throws Exception {

        String pathString = null;
        if (file != null) {
            //获取上传的文件名称
            String filename = file.getOriginalFilename();
            //文件上传时，chrome与IE/Edge对于originalFilename处理方式不同
            //chrome会获取到该文件的直接文件名称，IE/Edge会获取到文件上传时完整路径/文件名
            //Check for Unix-style path
            int unixSep = filename.lastIndexOf('/');
            //Check for Windows-style path
            int winSep = filename.lastIndexOf('\\');
            //cut off at latest possible point
            int pos = (winSep > unixSep ? winSep : unixSep);
            if (pos != -1) {
                filename = filename.substring(pos + 1);
                pathString = uploadPath + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + filename;//上传到本地
            } else {
                pathString = uploadPath + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + filename;//上传到本地
            }
        }
        //计数器
        int count=-1;
        try {
            File files = new File(pathString);//在内存中创建File文件映射对象
            //打印查看上传路径
            System.out.println(pathString);
            if (!files.getParentFile().exists()) {//判断映射文件的父文件是否真实存在
                files.getParentFile().mkdirs();//创建所有父文件夹
            }
            file.transferTo(files);//采用file.transferTo 来保存上传的文件

            //将数据保存到List对象中去
            if (fileType == NOISE_TYPE) {
                fileNames_noise.add(file.getOriginalFilename());
                count=readNoiseFile(pathString);
                // System.out.println(list_noise);
            } else if (fileType == FLY_TYPE) {
                fileNames_fly.add(file.getOriginalFilename());
                count=readFlyFile(pathString);
                //System.out.println(list_fly);
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return "{\"code\":0, \"msg\":\"success\", \"fileUrl\":\"" + pathString + "\", \"count\":\""+count+"\"}";

    }


    public static ArrayList<FlyRow> readFlyFile1(String path) throws IOException, InvalidFormatException {
        File xlsFile = new File(path);
        ArrayList<FlyRow> data = new ArrayList<>();
        // 工作表
        try (Workbook workbook = WorkbookFactory.create(xlsFile)) {

            // 表个数。
            int numberOfSheets = workbook.getNumberOfSheets();

            // 遍历表。
            for (int i = 0; i < numberOfSheets; i++) {
                Sheet sheet = workbook.getSheetAt(i);

                // 行数。
                int rowNumbers = sheet.getLastRowNum() + 1;

                // Excel第一行。
                Row temp = sheet.getRow(0);
                if (temp == null) {
                    continue;
                }
                //读取列数
                int cells = temp.getPhysicalNumberOfCells();
                //存储数据的数组
                String[] data_row = new String[cells];
                // 读数据。
                for (int row = 1; row < rowNumbers; row++) {
                    Row r = sheet.getRow(row);
                    for (int col = 0; col < cells; col++) {
                        data_row[col] = r.getCell(col).toString();
                    }
                    ;
                    data.add(new FlyRow(data_row));
                }
            }
        }
        return data;
    }


    //读取噪声数据， 返回结果的arraylist集合，线程不安全，对于安全性问题可采用vector，性能会有所下降
//    public static ArrayList<SyncRow> readNoiseFile(String path) throws IOException {
//        File file = new File(path);
//        ArrayList<SyncRow> res=new ArrayList<>();
//        FileReader fileReader = new FileReader(file);
//        BufferedReader bufferedInputStream = new BufferedReader(fileReader);
//        String line = bufferedInputStream.readLine();
//        String[] headName = regex_noise(line);
//        //读取每一行文件，保存到list对象
//        while ((line = bufferedInputStream.readLine()) != null) {
//            String[] data = regex_noise(line);
//            //将行数据加入到结果集
//            res.add(new SyncRow(Double.parseDouble(data[0]), Double.parseDouble(data[1]), Double.parseDouble(data[2]), Double.parseDouble(data[3])));
//
////            noiseRow.setTime(Float.parseFloat(data[0]));
////            //读取声道
////            for (int i = 1; i < data.length; ++i) {
////                noiseRow.getVocal_tract().add(Double.parseDouble(data[i]));
////            }
////            list_noise.add(noiseRow);
//        }
//        return res.size()==0?null:res;
//    }

    //读取飞行参数数据
    public static Integer readFlyFile(String path) throws IOException, InvalidFormatException {
        File xlsFile = new File(path);

        // 工作表
        try (Workbook workbook = WorkbookFactory.create(xlsFile)) {

            // 表个数。
            int numberOfSheets = workbook.getNumberOfSheets();

            // 遍历表。
            for (int i = 0; i < numberOfSheets; i++) {
                Sheet sheet = workbook.getSheetAt(i);

                // 行数。
                int rowNumbers = sheet.getLastRowNum() + 1;

                // Excel第一行。
                Row temp = sheet.getRow(0);
                if (temp == null) {
                    continue;
                }
                //读取列数
                int cells = temp.getPhysicalNumberOfCells();
                //确定声道数

                //存储数据的数组
                String[] data_row = new String[cells];
                // 读数据。
                for (int row = 1; row < rowNumbers; row++) {
                    Row r = sheet.getRow(row);
                    for (int col = 0; col < cells; col++) {
                        data_row[col] = r.getCell(col).toString();
                    };
                    list_fly.add(new FlyRow(data_row));
                }
            }
        }
        return  list_fly.size();
    }


    //读取噪声数据
    public static Integer readNoiseFile(String path) throws IOException {
        File file = new File(path);
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedInputStream = new BufferedReader(fileReader);
        String line = bufferedInputStream.readLine();
        String[] headName = regex_noise(line);
        //读取每一行文件，保存到list对象
        while ((line = bufferedInputStream.readLine()) != null) {
            String[] data = regex_noise(line);
            NoiseRow noiseRow = new NoiseRow();
            noiseRow.setTime(Float.parseFloat(data[0]));
            //读取声道
            for (int i = 1; i < data.length; ++i) {
                noiseRow.getVocal_tract().add(Double.parseDouble(data[i]));
            }
            list_noise.add(noiseRow);
        }
        //确定声道数
        trackNum=list_noise.get(0).getVocal_tract().size();
        return list_noise.size();
    }

    //正则表达式
    public static String[] regex_noise(String line) {
        List<String> res = new ArrayList();
        Matcher m = Pattern.compile("\\S+").matcher(line);
        while (m.find()) {
            res.add(m.group());
        }
        String[] res_arr = (String[]) res.toArray(new String[res.size()]);
        return res_arr;
    }

    //获取到List中的数据进行分组，并转化为json对象
    public static String getOrginData(ArrayList<NoiseRow> list) {

        if(list.isEmpty()){
            return "{\"msg\":\"您还没上传数据\"";
        }
        String res = "{";
        //List转数组
        double time[] = new double[list.size()];
        //二维数组，二维时间，一维是声道
        double Vocal_tract[][] = new double[list.get(0).getVocal_tract().size()][list.size()];
        for (int i = 0; i < list.size(); i++) {
            NoiseRow row = list.get(i);
            time[i] = row.getTime();
            for (int j = 0; j < row.getVocal_tract().size(); j++) {
                Vocal_tract[j][i] = row.getVocal_tract().get(j);
            }
        }

        //数组转json
        JSONArray jsonArray = JSONArray.fromObject(time);
        String s = jsonArray.toString();
        //一定要加引号
        res += "\"time\":" + s;
/*        for (int i = 0; i < Vocal_tract.length; i++) {
            JSONArray arr = JSONArray.fromObject(Vocal_tract[i]);
            String s_arr = arr.toString();
            res += ",\"Vocal_tract" + i + "\":" + s_arr;

        }*/
        res+=",\"Vocal_tract\":"+JSONArray.fromObject(Vocal_tract).toString();
        res += ", \"msg\":\"success\",\"numVocal\":"+Vocal_tract.length+"}";
        System.out.println(res);
        return res;
    }

    /*获取到3D声学球数据，并转化为json对象**/
    public static String get3DNoise() {
        String res = "{";
        double res_arr[][] = new double[10][10];

        return res;
    }



    /**
     * 时间同步后的数据
     *
     * @param gps_ground
     * @param ori
     * @param freq
     * @return
     * @throws Exception
     */
    public static Map<NoiseRow, FlyRow> sync(double[] gps_ground, double ori, double freq) throws Exception {

/*        readFlyFile("E:\\upload\\20210510174330_flyInfo.xls");
        readNoiseFile("E:\\upload\\20210510174331_噪声数据（非涉密非商密）.txt");*/
        //判断是否上传文件

        if(list_noise.isEmpty()){
            return null;
        }
        else if(list_fly.isEmpty()){
            return null;
        }

        for (NoiseRow noiseRow : list_noise) {
            noise_fly.put(noiseRow, null);
        }

        for (FlyRow flyRow : list_fly) {
            //开始进行时间同步
            double T = 10 / freq;
            double begin = Interpolation.getBegin(flyRow, ori, new GPS(gps_ground));
            for (NoiseRow key : noise_fly.keySet()) {
                if (key.getTime() >= begin && key.getTime() <= begin + T)
                    noise_fly.put(key, flyRow);
            }
        }

        return noise_fly;
    }

    public static void syncDatatrans(Map<String,String> data){
        gps_ground=new double[7];
        System.out.println(data.get("jingDu"));
        String[] jingDus = data.get("jingDu").split("\\.");
        System.out.println(Arrays.toString(jingDus));
        gps_ground[0]=Double.parseDouble(jingDus[0]);
        gps_ground[1]=Double.parseDouble(jingDus[1]);
        gps_ground[2]=Double.parseDouble(jingDus[2]);
        String[] weiDus = data.get("weiDu").split("\\.");
        gps_ground[3]=Double.parseDouble(weiDus[0]);
        gps_ground[4]=Double.parseDouble(weiDus[1]);
        gps_ground[5]=Double.parseDouble(weiDus[2]);
        gps_ground[6]=Double.parseDouble(data.get("gaoDu"));
        ori=Double.parseDouble(data.get("timeStart"));
        freq=Double.parseDouble(data.get("timeStep"));
    }

    /**
     * Map_3D_Noise转化为json
     */
    public static String toJson_Map_3D_Noise(){
        StringBuilder sb=new StringBuilder("{");
        int c=0;
        if(ControlUtil.Map_3D_Noise!=null) {
            for (Map.Entry e : (Set<Map.Entry>) ControlUtil.Map_3D_Noise.entrySet()) {
                if (c == 0)
                    sb.append("\"" + e.getKey().toString() + "\":\"" + e.getValue().toString() + "\"");
                else
                    sb.append("," + "\"" + e.getKey().toString() + "\":\"" + e.getValue().toString() + "\"");
                c++;
            }
        }
        sb.append("}");
        return sb.toString();
    }
    //保存插值函数
    public static void temp_3D_noise(LinkedHashMap reqMap){
        Map_3D_Noise=reqMap;
    }
    //id生成器
    public static Integer idGenerator(){
        return new Random().nextInt(10000);
    }
    //求飞行数据的平均值, 返回flystatus对象
    public static FlyStatus calAverFlyRow() {
        FlyStatus fs=new FlyStatus();
        fs.setId(ControlUtil.idGenerator());
        fs.setSphere_id(ControlUtil.idGenerator());
        fs.setIndicated_airspeed(ControlUtil.list_fly.stream().map(FlyRow::getIndicated_airspeed).collect(Collectors.averagingDouble(Double::doubleValue)));
        fs.setTorque(ControlUtil.list_fly.stream().map(FlyRow::getTorque).collect(Collectors.averagingDouble(Double::doubleValue)));
        fs.setRotor_speed(ControlUtil.list_fly.stream().map(FlyRow::getRotor_speed).collect(Collectors.averagingDouble(Double::doubleValue)));
        fs.setFuel_weight(ControlUtil.list_fly.stream().map(FlyRow::getFuel_weight).collect(Collectors.averagingDouble(Double::doubleValue)));
        fs.setBarometric_height(ControlUtil.list_fly.stream().map(FlyRow::getBarometric_height).collect(Collectors.averagingDouble(Double::doubleValue)));
        fs.setStatic_temperature(ControlUtil.list_fly.stream().map(FlyRow::getStatic_temperature).collect(Collectors.averagingDouble(Double::doubleValue)));
        return fs;
    }
    public static void main(String[] args) throws IOException {
//        String a="12.34.12";
//        final String[] split = a.split("\\.");
//        System.out.println(Arrays.toString(split));
        ControlUtil.Map_3D_Noise=new LinkedHashMap();
        ControlUtil.Map_3D_Noise.put("a","1");
        ControlUtil.Map_3D_Noise.put("b","2");
        System.out.println(ControlUtil.toJson_Map_3D_Noise());
    }


}
